package qst.com.bacK.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import qst.com.bacK.exception.ExamException;
import qst.com.bacK.mapper.AssessmentsMapper;
import qst.com.bacK.mapper.ExamMapper;
import qst.com.bacK.mapper.ScheduleMapper;
import qst.com.bacK.pojo.entity.*;
import qst.com.bacK.question.QuestionQueryParam;
import qst.com.bacK.service.ExamService;
import qst.com.bacK.service.QuestionService;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;

/**
 * Author:   msh
 * Date:     2024/10/10 上午12:06
 * Description:
 */

@Service
public class ExamServiceImpl implements ExamService {
    @Autowired
    private ExamMapper examMapper;
    @Autowired
    private ScheduleMapper scheduleMapper;
    @Autowired
    private AssessmentsMapper assessmentsMapper;
    @Autowired
    private QuestionService questionService;

    @Override
    public List<Schedule> findScheduleByTestPersonnel(TestPersonnel personnel) {
        try {
            /**
             * 查询本学生已经参加的所有考试
             */
            List<Exam> exams = examMapper.findByTestPersonnel(personnel.getId());

            /**
             * 本学生所在班级所有的考试安排
             */
            List<Schedule> schedules = scheduleMapper
                    .findByTeamId(personnel.getTeamId());
            Map<Integer, Schedule> map = new HashMap<>();
            for (Schedule h : schedules) {
                h.setAssessmentType(assessmentsMapper.findById(h.getAssessmentId()));
                map.put(h.getId(), h);
            }
            // 标记已经考过的考试
            for (Exam m : exams) {
                try {
                    map.get(m.getScheduleId()).getExtras().put("exam", m);
                } catch (Exception e) {
                    // TODO: handle exception
                    e.getMessage();

                }
            }
            return schedules;
        } catch (Exception ex) {
            throw new ExamException("查询考试出错", ex);
        }
    }

    @Override
    public List<Exam> examResult(Integer id) throws SQLException {
        return examMapper.findById(id);
    }

    @Override
    public Exam begin(TestPersonnel personnel, Integer scheduleId) {
        try {
            Schedule schedule = scheduleMapper.findById(scheduleId);
            Exam exam = scheduleMapper.findByTestPersonnelAndSchedule(personnel.getId(),
                    schedule.getId());
            // 判断该考生能否参加本次考试
            isCanExam(personnel, exam, schedule);
            if (exam == null) {
                exam = new Exam();
                exam.setTestPersonnelId(personnel.getId());
                exam.setScheduleId(scheduleId);
                exam.setBeginTime(new Timestamp(System.currentTimeMillis()));
            }
            List<ExamQuestion> examQustions = new ArrayList<>();
            QuestionQueryParam param = new QuestionQueryParam();
            param.setAssessmentId(schedule.getAssessmentId());
            param.setStatus(2);// 有效
            // 抽取单选题
            param.setType(1);// 单选题
            examQustions.addAll(findQuestion(personnel.getId(), param, (schedule.getQuestionNumber() / 4), 2
            ));
            // 抽取多选题
            param.setType(2);// 多选题
            examQustions.addAll(findQuestion(personnel.getId(), param, (schedule.getQuestionNumber() / 4), 2
            ));
            param.setType(3);// 多选题
            examQustions.addAll(findQuestion(personnel.getId(), param, (schedule.getQuestionNumber() / 4), 2
            ));
            param.setType(4);// 多选题
            examQustions.addAll(findQuestion(personnel.getId(), param, (schedule.getQuestionNumber() / 4), 2
            ));
            exam.setExamQuestions(examQustions);

            return exam;
        } catch (SQLException e) {
            throw new ExamException("数据库访问出错，不能开始考试", e);
        }
    }

    private List<ExamQuestion> findQuestion(int stuId,
                                            QuestionQueryParam param, int count, int score) {

        List<Question> questions = questionService.find(param);
        // 打乱list的顺序和洗牌一样
        Collections.shuffle(questions);
        // count 为考试安排中指定的试题数量，questions.size()为按要求查找出来的试题数量
        count = questions.size() > count ? count : questions.size();
        // 如果按要求查找出来的试题数量为50，考试只要求20，所以截取20个题
        List<Question> tempList = questions.subList(0, count);

        List<ExamQuestion> examQustions = new ArrayList<>();
        for (Question q : tempList) {
            ExamQuestion eq = new ExamQuestion();
            eq.setQuestionId(q.getId());
            eq.setQuestion(q);
            eq.setTestPersonnelId(stuId);
            // 考试安排时，会指定每个单选或者多选的分数
            eq.setScore(score);
            examQustions.add(eq);
        }
        return examQustions;
    }

    private boolean isCanExam(TestPersonnel personnel, Exam exam, Schedule schedule) {
        if (exam != null) {
            throw new ExamException("已经考过了，不能再考");
        }
        if (schedule.getTeamId() != personnel.getTeamId()) {
            throw new ExamException("不是指定批次的参测人员，不能参加考试");
        }
        if (schedule.getStatus() == 0) {
            throw new ExamException("本次考试已取消");
        }
        if (schedule.getStatus() == 1) {
            throw new ExamException("本次考试还没有开始");
        }
        if (schedule.getStatus() == 3) {
            throw new ExamException("本次考试已结束");
        }
        return true;
    }
}
